package com.siyoumi.app.external_api.aliyun;

import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;
import com.siyoumi.app.external_api.aliyun.entity.EnvAlipayOss;
import com.siyoumi.component.LogPipeLine;
import com.siyoumi.component.http.XHttpContext;
import com.siyoumi.exception.EnumSys;
import com.siyoumi.util.XDate;
import com.siyoumi.util.XReturn;
import com.siyoumi.util.XStr;
import com.siyoumi.validator.XValidator;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.FileInputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

//阿里云oss
@Data
@Slf4j
public class ApiAliYunOss {
    EnvAlipayOss config;

    /**
     * 实例化
     *
     * @param config
     */
    static public ApiAliYunOss of(EnvAlipayOss config) {
        ApiAliYunOss api = new ApiAliYunOss();
        api.setConfig(config);
        return api;
    }

    protected String getBucketName() {
        return getConfig().getBucket_name();
    }


    //https://help.aliyun.com/zh/oss/developer-reference/simple-upload-11?spm=a2c4g.11186623.0.0.11e25b0fDf1Hcj
    public XReturn uploadFileByRoot(String root, String filePath) {
        File file = new File(filePath);
        if (!file.exists()) {
            return XReturn.getR(20052, "文件不存在");
        }

        //app/2025-01-05/3.jpg
        String ossFilePath = XStr.format("{0}/{1}/{2}"
                , root
                , XDate.toDateString() //日期目录
                , file.getName()
        );

        return uploadFile(ossFilePath, file);
    }

    /**
     * 上传文件
     *
     * @param ossFilePath sso保存路径
     * @param file        文件
     * @return
     */
    public XReturn uploadFile(String ossFilePath, File file) {
        //String[] fileArr = filePath.split("/");
        //String fileName = fileArr[fileArr.length - 1];
        //String fileName = file.getName();
        //LogPipeLine.getTl().setLogMsg("fileName: ", fileName);
        LogPipeLine.getTl().setLogMsg("ossFilePath: ", ossFilePath);

        OSS ossClient = getClient();
        XReturn r;
        try {
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(getBucketName(), ossFilePath, file);
            // 创建PutObject请求。
            PutObjectResult result = ossClient.putObject(putObjectRequest);

            r = XReturn.getR(0);
            r.setData("request_id", result.getRequestId());
            r.setData("oss_file_path", ossFilePath);
        } catch (OSSException oe) {
            log.error(oe.getMessage());

            r = EnumSys.SYS.getR(oe.getErrorMessage());
            r.setData("error_code", oe.getErrorCode());
            r.setData("request_id", oe.getRequestId());
            r.setData("host_id", oe.getHostId());
        } catch (Exception ex) {
            ex.printStackTrace();

            log.error(ex.getMessage());
            r = EnumSys.SYS.getR();
            r.setErrMsg(ex.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }

        errHandle("uploadFile", r);

        return r;
    }

    /**
     * 文件列表
     *
     * @param root 搜索前缀，如：export
     */
    public List<OSSObjectSummary> fileList(String root) {
        OSS ossClient = getClient();
        XReturn r;
        List<OSSObjectSummary> files = new ArrayList<>();
        try {
            ListObjectsRequest request = new ListObjectsRequest(getBucketName());
            request.setPrefix(root);
            ObjectListing result = ossClient.listObjects(request);

            r = XReturn.getR(0);
            files = result.getObjectSummaries();
        } catch (OSSException oe) {
            log.error(oe.getMessage());

            r = EnumSys.SYS.getR();
            r.setErrMsg(oe.getErrorMessage());
            r.setData("error_code", oe.getErrorCode());
            r.setData("request_id", oe.getRequestId());
            r.setData("host_id", oe.getHostId());
        } catch (Exception ex) {
            ex.printStackTrace();

            log.error(ex.getMessage());
            r = EnumSys.SYS.getR();
            r.setErrMsg(ex.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }

        errHandle("fileList", r);
        if (r.err()) {
            XValidator.err(r);
        }

        return files;
    }

    /**
     * 删除列表
     */
    public XReturn delFileList(List<String> keys) {
        OSS ossClient = getClient();
        XReturn r;
        try {
            DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(getBucketName()).withKeys(keys).withEncodingType("url");
            DeleteObjectsResult deleteObjectsResult = ossClient.deleteObjects(deleteObjectsRequest);
            List<String> deletedObjects = deleteObjectsResult.getDeletedObjects();

            r = XReturn.getR(0);
            r.setData("delete_result", deletedObjects);

        } catch (OSSException oe) {
            log.error(oe.getMessage());

            r = EnumSys.SYS.getR();
            r.setErrMsg(oe.getErrorMessage());
            r.setData("error_code", oe.getErrorCode());
            r.setData("request_id", oe.getRequestId());
            r.setData("host_id", oe.getHostId());
        } catch (Exception ex) {
            ex.printStackTrace();

            log.error(ex.getMessage());
            r = EnumSys.SYS.getR();
            r.setErrMsg(ex.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }

        errHandle("fileList", r);
        if (r.err()) {
            XValidator.err(r);
        }

        return r;
    }

    /**
     * 删除x天前的目录及目录下的文件
     *
     * @param root       前缀，如：export
     * @param delDirList 删除x天前数据
     */
    public XReturn delDirAndFile(String root, List<String> delDirList) {
        List<OSSObjectSummary> files = fileList(root);
        List<String> fileKeys = new ArrayList<>();

        //LocalDateTime deleteDate = Helper.funcToday().minusDays(beforeDay);
        //Date date = Date.from(deleteDate.atZone(ZoneId.systemDefault()).toInstant());
        //log.debug("删除日期：{}", Helper.funcToDateTimeString(deleteDate));

        for (OSSObjectSummary file : files) {
            if (root.equals(file.getKey())) continue;

            String[] fileArr = file.getKey().split("/");
            if (fileArr.length < 1) {
                continue;
            }
            String dirName = fileArr[1];
            if (delDirList.contains(dirName)) {
                log.debug("file_key: {}, dirName: {}", file.getKey(), dirName);
                fileKeys.add(file.getKey());
            }
        }

        if (fileKeys.size() > 0) {
            delFileList(fileKeys);
        }

        return EnumSys.OK.getR();
    }

    public XReturn generatePresignedUrl(String ossfilePath) {
        return generatePresignedUrl(ossfilePath, 60);
    }

    /**
     * 生成访问链接，60秒有效
     *
     * @param ossfilePath  oss路径
     * @param expireSecond 有效时长（秒）
     */
    public XReturn generatePresignedUrl(String ossfilePath, int expireSecond) {
        OSS ossClient = getClient();
        XReturn r;
        try {
            // 设置签名URL过期时间，单位为毫秒。本示例以设置过期时间为1小时为例。
            Date expiration = new Date(new Date().getTime() + expireSecond * 1000L);
            // 生成以GET方法访问的签名URL，访客可以直接通过浏览器访问相关内容。
            URL url = ossClient.generatePresignedUrl(getBucketName(), ossfilePath, expiration);
            r = XReturn.getR(0);
            r.setData("url", url.toString());
        } catch (OSSException oe) {
            log.error(oe.getMessage());

            r = EnumSys.SYS.getR();
            r.setErrMsg(oe.getErrorMessage());
            r.setData("error_code", oe.getErrorCode());
            r.setData("request_id", oe.getRequestId());
            r.setData("host_id", oe.getHostId());
        } catch (Exception ex) {
            ex.printStackTrace();

            log.error(ex.getMessage());
            r = EnumSys.SYS.getR();
            r.setErrMsg(ex.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }

        return r;
    }


    protected void errHandle(String method, XReturn r) {
        if (r.err()) {
            LogPipeLine.getTl().saveDb(method, XHttpContext.getX());
        } else {
            LogPipeLine.getTl().clear();
        }
    }

    @SneakyThrows
    protected OSS getClient() {
        // yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1（杭州）为例，Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
        String endPoint = getConfig().getEndpoint();

        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        //clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);

        //OSS ossClient = OSSClientBuilder.create()
        //        .region(getConfig().getApi_region())
        //        .endpoint(endPoint)
        //        .clientConfiguration(clientBuilderConfiguration)
        //        .build();

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endPoint, getConfig().getAccess_key_id(), getConfig().getAccess_key_secret(), clientBuilderConfiguration);

        return ossClient;
    }
}

